/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.loja.view.component.factory;

import br.com.loja.view.component.composition.factory.CompositionToOneFactory;
import br.com.loja.view.component.composition.factory.CompositionToManyFactory;
import br.com.loja.view.component.aggregation.factory.AggregationToOneFactory;
import br.com.loja.view.component.aggregation.factory.AggregationToManyFactory;
import static br.com.loja.util.reflection.ReflectionUtil.isEntity;
import br.com.loja.view.swing.Composition;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

/**
 *
 * @author DavidLuiz
 */
public class ComponentProducer {

    private final Field field;

    public ComponentProducer(Field field) {
        this.field = field;
    }

    public ComponentFactory getComponentFactory() {

        if (isToMany()) {
            if (isComposition()) {
                return new CompositionToManyFactory(getClassType());
            }

            return new AggregationToManyFactory(getClassType());

        }

        if (!isComposition()) {
            return new AggregationToOneFactory(getClassType());
        }

        return new CompositionToOneFactory(getClassType());

    }

    private boolean isToMany() {
        return Collection.class.isAssignableFrom(field.getType());
    }

    private boolean isComposition() {
        Class<?> type = getClassType();

        if (isEntity(type)) {

            Composition annotation = type.getAnnotation(Composition.class);

            if (annotation == null) {
                return false;
            }

            return annotation.value().isAssignableFrom(field.getDeclaringClass());

        }

        return !type.isEnum();

    }

    private Class<?> getClassType() {

        if (isToMany()) {
            ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            return (Class<?>) actualTypeArguments[0];
        }

        return field.getType();

    }

}
